package com.usian.skill.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.usian.skill.common.CodeMsg;
import com.usian.skill.common.Result;
import com.usian.skill.mapper.GoodsMapper;
import com.usian.skill.mq.MQSender;
import com.usian.skill.mq.SkillMessage;
import com.usian.skill.pojo.OrderInfo;
import com.usian.skill.pojo.SkillOrder;
import com.usian.skill.service.GoodsService;
import com.usian.skill.service.SkillGoodsService;
import com.usian.skill.service.SkillOrderService;
import com.usian.skill.service.SkillService;
import com.usian.skill.util.MD5Util;
import com.usian.skill.util.UUIDUtil;
import com.usian.skill.vo.GoodsVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;

@Controller
@RequestMapping("/skill")
public class SkillController implements InitializingBean {

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private SkillOrderService skillOrderService;
    @Autowired
    private SkillService skillService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MQSender mqSender;
    //减少对redis的访问
    private HashMap<Long, Boolean> localOverMap = new HashMap<>();
    /**
     * 完成库存的初始化
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> goodsVo = goodsService.findAllByDB();
        if (!CollectionUtils.isEmpty(goodsVo)){
            for (GoodsVo vo : goodsVo) {
                //取出所有商品库存并存入redis
                stringRedisTemplate.opsForValue().set("stockCount"+vo.getId(),vo.getStockCount().toString());
                //商品库存充足就设置为false
                localOverMap.put(vo.getId(),false);
            }
        }
    }

    @RequestMapping("/{path}/skillGood")
    @ResponseBody
    public Result skillGood(@PathVariable("path") String path, HttpSession session, Long goodsId, Model model){
        String userId = (String) session.getAttribute("userId");
        if (userId==null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        //查库存
//        GoodsVo goodsVo = goodsService.getGoodsVoByGoodsId(goodsId);
        //取出redis中的库存
       if (localOverMap.get(goodsId)){
          return Result.error(CodeMsg.MIAO_SHA_OVER);
       }
        String stockCount = stringRedisTemplate.opsForValue().get("stockCount" + goodsId);
        if (Integer.parseInt(stockCount)<=0){
            localOverMap.put(goodsId,true);
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }else {
            //预减库存    decrement方法完成数量减一
            stringRedisTemplate.opsForValue().decrement("stockCount" + goodsId);
        }
        //查看是否秒杀过
        SkillOrder skillOrder = skillOrderService.getOne(Wrappers.
                <SkillOrder>lambdaQuery().eq(SkillOrder::getGoodsId, goodsId).eq(SkillOrder::getUserId, userId));
        if (skillOrder!=null){
            //将预减的加上，相当于回滚
            stringRedisTemplate.opsForValue().increment("stockCount" + goodsId);
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }
        //入队
        SkillMessage skillMessage = new SkillMessage();
        skillMessage.setGoodsId(goodsId);
        skillMessage.setUserId(userId);
        mqSender.sendSkillMSG(skillMessage);
        //告知用户正在排队
        return Result.success(0);
    }

    //获取秒杀结果
    @RequestMapping(value = "/result",method = RequestMethod.GET)
    @ResponseBody
    public Result<Long> miaoshaResult(Model model,HttpSession session,@Param("goodsId") Long goodsId){
        String userId = (String) session.getAttribute("userId");
        if (userId==null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        long result=skillService.getSkillResult(userId,goodsId);
        return Result.success(result);
    }


    public String createPiacoshPath(String user,Long goodsId){
        String s = MD5Util.md5(UUIDUtil.uuid() + "666");
        stringRedisTemplate.opsForValue().set(user+"random"+goodsId,s);
        return s;
    }

    public boolean checkPath(String user,Long goodsId,String path){
        String random = stringRedisTemplate.opsForValue().get(user+"random"+goodsId);
        return random.equals(path);
    }

    @RequestMapping("path")
    @ResponseBody
    public Result<String> getSkillPath(HttpSession session,
                                       @RequestParam("goodsId") Long goodsId){
        String user=(String)session.getAttribute("userId");
        if(user==null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        String path=createPiacoshPath(user,goodsId);
        return Result.success(path);
    }

    @RequestMapping(value="/verifyCode", method= RequestMethod.GET)
    @ResponseBody
    public Result<String> getMiaoshaVerifyCod(HttpServletResponse response, HttpSession session,
                                              @RequestParam("goodsId")long goodsId) {
        String user=(String)session.getAttribute("userId");
        if(user == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        try {
            BufferedImage image  = skillService.createVerifyCode(user, goodsId);
            OutputStream out = response.getOutputStream();
            ImageIO.write(image, "JPEG", out);
            out.flush();
            out.close();
            return null;
        }catch(Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.MIAOSHA_FAIL);
        }
    }

}
